﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Microsoft.Win32;

/* 
 *  主窗体与订阅函数、全局变量集合
 *  创建时间：2019/11/10 wj
 *  修改时间：2019/12/11 wj
 */

namespace Window.Function
{

    public class UpdateScorllRichTextBox
    {
        /** 
           * \brief 订阅函数：点亮指定行数[仅限于运行与停止模式下使用]
           *
           * \param[in] index  对应行数
           * \param[in] lineNumber  对应行个数
           */
        public void LightIndexCode(RichTextBox TxtEdit, int index, uint lineNumber)
        {
            TxtEdit.Focus();
            // 判断点亮位置是否处于首行状态 2019.12.12 wj 增
            if (0 == index) 
            {
                TxtEdit.SelectAll();
                TxtEdit.SelectionBackColor = Color.White;
                TxtEdit.SelectionLength = 0;
            }
            else
            {
                 // 获取变动前编辑栏位置 2019.11.27 wj 
                 for (int i = 0; i < lightLineIndexList.Count; i++)
                {
                    LightSingleIndexCode(TxtEdit, lightLineIndexList[i], Color.White);
                }
            }
            lightLineIndexList.Clear();
            for (int i = index; i < index + lineNumber; i++)
            {
                lightLineIndexList.Add(i);
                LightSingleIndexCode(TxtEdit, i, Color.DarkSeaGreen);
            }

            // 判断是否为最后一行位置 2019.12.12 wj 增
            int txtRowNum =TxtEdit.Text.Split('\n').Length - 1;
            if (txtRowNum == index)
            {
                IsAutoLastLine = true;
            }
            else
            {
                IsAutoLastLine = false;
            }
        }

        /** 
          * \brief 基础函数：点亮指定单行行数
          *
          * \param[in] index  对应行数
          * \param[in] lineColor  点亮对应颜色
          */
        public void LightSingleIndexCode(RichTextBox TxtEdit, int index, Color lineColor)
        {
            TxtEdit.Focus();
            int currentLineFromCharIndex = GetCharFromLineIndex(index, TxtEdit.Text);
            int nextLineFromCharIndex = GetCharFromLineIndex((int)(index + 1), TxtEdit.Text);
            TxtEdit.Select(currentLineFromCharIndex, nextLineFromCharIndex - currentLineFromCharIndex);
            TxtEdit.SelectionBackColor = lineColor;
            TxtEdit.SelectionLength = 0;
        }

        #region TxtEditLine Related 文本编辑模块位置函数相关**************************************************/
    
	    /** 
          * \brief 界面控制与显示相关 2019.11.08 wj 增
          */
        private void ShowLineNum(RichTextBox TxtEdit, RichTextBox TxtRow)
        {
            TxtRow.Text = String.Empty;              //计算行高，行数            
            int linesLength = 0;
            var pFirst = TxtEdit.GetPositionFromCharIndex(0);
            var pEnd = TxtEdit.GetPositionFromCharIndex(TxtEdit.Text.Length);
            if (pEnd.Y > pFirst.Y)
            {
                var pSecondLine = TxtEdit.GetPositionFromCharIndex(TxtEdit.GetFirstCharIndexFromLine(1));
                var lineHeight = pSecondLine.Y - pFirst.Y;
                string[] stringList = TxtEdit.Text.Replace("\r", "").Split('\n');
                if (String.IsNullOrEmpty(stringList[stringList.Length - 1]))
                {
                    TxtEdit.Height += 4;
                }
                linesLength = stringList.Length;
            }
            else
            {
                linesLength = 1;
            }
            //生成行数            
            for (var i = 0; i < linesLength; i++)
            {
                if (i + 1 == linesLength)
                {
                    TxtRow.AppendText(String.Format("{0}", i + 1));
                }
                else
                {
                    TxtRow.AppendText(i + 1 + "\n");
                }
            }
            //行号右对齐            
            TxtRow.SelectAll();
            TxtRow.SelectionAlignment = HorizontalAlignment.Right;
        }

        //同步滚动        
        private void SyncSrollLocation(RichTextBox TxtEdit, RichTextBox TxtRow)
        {
            //首行首字符初始位置            
            var p = new Point(2, 2);
            //计算行高           
            int lineHeight = 0;
            var pFirst = TxtEdit.GetPositionFromCharIndex(0);//首行位置           
            var pEnd = TxtEdit.GetPositionFromCharIndex(TxtEdit.Text.Length);//最后一行位置           
            if (pEnd.Y > pFirst.Y)//排除只有一行的情况            
            {
                var pSecondLine = TxtEdit.GetPositionFromCharIndex(TxtEdit.GetFirstCharIndexFromLine(1));
                lineHeight = pSecondLine.Y - pFirst.Y;
            }
            //滚动高度 即首行位置移动高度                
            int scrollHeight = p.Y - pFirst.Y;
            //滚动到的行的位置  由于滚动大都并非整行滚动 所以四舍五入 ***程序的误差就在这里 
            var scrollToLine = 0;
            if (!String.IsNullOrEmpty(TxtEdit.Text))
            {
                scrollToLine = (int)Math.Round((double)((scrollHeight + 6) / lineHeight), MidpointRounding.AwayFromZero);
                int sStart = TxtRow.GetFirstCharIndexFromLine((scrollToLine));//左侧行号 当前滚动到行 首字符位置               
                if (sStart >= 0)
                {
                    TxtRow.SelectionStart = sStart;
                    TxtRow.SelectionLength = 0;
                    TxtRow.ScrollToCaret();
                }
            }
        }
	
        /**
         * \brief  计算滚动位置 2019.11.28 wj 增  
         * 
         * \retval  scrollToLine 计算出的滚动位置
         */
        private int CalculateSrollLocation(RichTextBox TxtEdit, RichTextBox TxtRow)
        {
            //首行首字符初始位置
            int scrollToLine = 0;
            var p = new Point(1, 1);
            //计算行高           
            int lineHeight = 0;
            var pFirst = TxtEdit.GetPositionFromCharIndex(0);//首行位置           
            var pEnd = TxtEdit.GetPositionFromCharIndex(TxtEdit.Text.Length);//最后一行位置           
            if (pEnd.Y > pFirst.Y)//排除只有一行的情况            
            {
                var pSecondLine = TxtEdit.GetPositionFromCharIndex(TxtEdit.GetFirstCharIndexFromLine(1));
                lineHeight = pSecondLine.Y - pFirst.Y;
            }
            //滚动高度 即首行位置移动高度                
            int scrollHeight = p.Y - pFirst.Y;
            try
            {
                //滚动到的行的位置  由于滚动大都并非整行滚动 所以四舍五入 ***程序的误差就在这里           
                scrollToLine = (int)Math.Round((double)((scrollHeight + 6) / lineHeight), MidpointRounding.AwayFromZero);
            }
            catch
            {
                scrollToLine = 0;
            }
            return scrollToLine;
        }
        #endregion

        /**
          * \brief 获取当前行数之前的字符个数
          * 
          * \param[in] index 序号
          * \param[in] txtData 当前文件内容 
          * \retval sum 字符个数
          */
        public static int GetCharFromLineIndex(int index, string txtData)
        {
            int sum = 0;
            String[] textGroup = txtData.Split('\n');
            // 处理代码可能存在超出数组范围界限的问题 2019.11.30 wj 
            if (index <= textGroup.Length)
            {
                for (int i = 0; i < index; i++)
                {
                    sum += textGroup[i].Length;
                }
            }
            else
            {
                for (int i = 0; i < textGroup.Length; i++)
                {
                    sum += textGroup[i].Length;
                }
            }
            // 只有大于0时才获取结果
            if (index > 0)
            {
                sum += index;
            }
            return sum;
        }


        // 2019.12.12 wj 是否触发自动跳转至最后一行的功能
        private bool isAutoLastLine = false;
        public bool IsAutoLastLine
        {
            get
            {
                return isAutoLastLine;
            }
            set
            {
                isAutoLastLine = value;
                OnNotifyPropertyChanged("IsAutoLastLine");
            }
        }

        // 存放曾经被点亮的行数  2019.11.28 wj 
        private List<int> lightLineIndexList = new List<int>();

    }
}
